/*** 
 * @Author: pengcheng
 * @Date: 2021-06-24 10:27:50
 * @LastEditTime: 2021-08-06 14:41:01
 * @LastEditors: pengcheng
 * @Description: 
 * @FilePath: /kylin-daq/src/DataTransmit.h
 */
#ifndef DATATRANSMIT_H
#define DATATRANSMIT_H

#include <QtCore/QtCore>
#include <QtNetwork/QtNetwork>

#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <QTimer>
#include "BaseModule.h"
#include "KylinDaqCommon.h"
#include <QDBusInterface>
#include <QDateTime>

class TransmitModule: public BaseModule
{
    Q_OBJECT
public:
    //	enum
    enum SendInfoStatus
    {
        OK = 0,
        FormatException = -1,
        NetworkAnomaly = -2,
        ServerException = -3,
        EncryptMd5Exception = -4,
        ServerReplyException = -5,
        UrlException = -6

    };
private:
    static constexpr const char *s_messageKey = "messages";
    //	protocol key
    static constexpr const char *s_replyErrorCodeKey = "code";
    static constexpr const char *s_replyErrorMsgKey = "msg";
    //	HTTP param
    static constexpr const char *s_requestTyepValue = "application/json";
    static constexpr const int32_t s_timerCountMsec = 2000;
    static constexpr const int32_t s_replyValidCode = 200;
    static constexpr const int32_t s_httpReplyValidCode = 200;
    //	API url
    static constexpr const char *s_uploadUrl = "collect-info-server/collect/info/submit";
    static constexpr const char *s_reuploadUrl = "collect-info-server/collect/info/re-submit";
    // conf
    static constexpr const char *s_moduleName = "TransmitModule";
    static constexpr const char *s_uploadIntervalKey = "UploadInterval";
    static constexpr const char *s_reuploadIntervalKey = "ReuploadInterval";
    static constexpr const char *s_numOfUploadedLinesKey = "NumOfUploadedLines";
    static constexpr const char *s_numOfReuploadedLinesKey = "NumOfReuploadedLines";
    static constexpr const char *s_uploadStateKey = "UploadState";
    static constexpr const char *s_uploadRealm = "UploadRealm";
    // HTTP HEAD
    static constexpr const char *s_httpUploadTimeStamp= "X-Upload-Timestamp";
    //
    static constexpr const char *s_uploadTimeKey="uploadTimestamp";
    //	NetworkManager
    QScopedPointer<QNetworkAccessManager> m_mannager;
    //	Timer
    QTimer *uploadTimer;
    QTimer *reuploadTimer;
    // singleton
    static QScopedPointer<TransmitModule> ms_instance;
    SendInfoStatus sendInfo(const QList<QString> &info, const QString &urlValue, const QString &requestHead, const int32_t timeCountMsec);
    // 检测url
    SendInfoStatus checkUrl(const QUrl &urlValue);
    // 整合发送信息
    SendInfoStatus mergeInfo(const QList<QString> &info,QByteArray &requestData);
    // 设置请求
    SendInfoStatus setRequest(QNetworkRequest &request,const QUrl &url,const QJsonObject &requestHeadObj);
    // 发送请求
    SendInfoStatus sendRequest(QNetworkRequest &request,const QByteArray &requestData,const int32_t timeCountMsec,int32_t &requestErrorCode,QString &requestErrorRelyStr);
    // 打印发送数据日志
    void printSendInfoLog(const QList<QString> &info,const SendInfoStatus &requestState,int32_t requestErrorCode,const QString &requestErrorRelyStr);
    //
    void sendUploadInfoNum();
    void sendReuploadInfoNum();
    // 判断网络是否连接
    bool networkIsConnected();
public:
    //	structure function
    explicit TransmitModule(QObject *parent = nullptr);
    virtual ~TransmitModule();
    //	singleton function
    static TransmitModule *instance(void);
public slots:
    void updateProperty(const QJsonObject &conf, const QJsonObject &defaultConf);
    void uploadInfo(const QList<qlonglong> &id,const QList<QString> &info,const QList<QString> & status, const QString &requestHead);
    void reuploadInfo(const QList<qlonglong> &id,const QList<QString> &info,const QList<QString> & status, const QString &requestHead);
    void setUploadTimerPollingInterval(qlonglong sec);
    void setReuploadTimerPollingInterval(qlonglong sec);
    void printConf();
signals:
    void uploadInfoSignal(qlonglong num);
    void reuploadInfoSignal(qlonglong num);
    void retUploadState(const QList<qlonglong> &id,const QList<QString> &info,const QList<QString> & status, const SendInfoStatus &sendInfoStatus);
    void retReuploadState(const QList<qlonglong> &id,const QList<QString> &info,const QList<QString> & status, const SendInfoStatus &sendInfoStatus);

    //	property
private:
    //	Q_PROPERTY
    Q_PROPERTY(qlonglong uploadInterval READ uploadInterval WRITE setUploadInterval NOTIFY uploadIntervalChanged)
    Q_PROPERTY(qlonglong reuploadInterval READ reuploadInterval WRITE setReuploadInterval NOTIFY reuploadIntervalChanged)
    Q_PROPERTY(qlonglong numOfUploadedLines READ numOfUploadedLines WRITE setNumOfUploadedLines NOTIFY numOfUploadedLinesChanged)
    Q_PROPERTY(qlonglong numOfReuploadedLines READ numOfReuploadedLines WRITE setNumOfReuploadedLines NOTIFY numOfReuploadedLinesChanged)
    Q_PROPERTY(QString uploadRealm READ uploadRealm WRITE setUploadRealm NOTIFY uploadRealmChanged)
    Q_PROPERTY(UploadState uploadState READ uploadState WRITE setUploadState NOTIFY uploadStateChanged)
    //	property var
    qlonglong m_numOfUploadedLines;
    qlonglong m_numOfReuploadedLines;
    qlonglong m_uploadInterval;
    qlonglong m_reuploadInterval;
    UploadState m_uploadState;
    QString m_uploadRealm;
public:
    //	property function
    qlonglong numOfUploadedLines() const
    {
        return m_numOfUploadedLines;
    }

    qlonglong numOfReuploadedLines() const
    {
        return m_numOfReuploadedLines;
    }

    qlonglong uploadInterval() const
    {
        return m_uploadInterval;
    }

    qlonglong reuploadInterval() const
    {
        return m_reuploadInterval;
    }

    UploadState uploadState() const
    {
        return m_uploadState;
    }

    QString uploadRealm() const
    {
        return m_uploadRealm;
    }
public slots:
    //	property slots
    void setNumOfUploadedLines(qlonglong numOfUploadedLines)
    {
        if (m_numOfUploadedLines == numOfUploadedLines)
            return;

        m_numOfUploadedLines = numOfUploadedLines;
        emit numOfUploadedLinesChanged(m_numOfUploadedLines);
    }

    void setNumOfReuploadedLines(qlonglong numOfReuploadedLines)
    {
        if (m_numOfReuploadedLines == numOfReuploadedLines)
            return;

        m_numOfReuploadedLines = numOfReuploadedLines;
        emit numOfReuploadedLinesChanged(m_numOfReuploadedLines);
    }

    void setUploadInterval(qlonglong uploadInterval)
    {
        if (m_uploadInterval == uploadInterval)
            return;

        m_uploadInterval = uploadInterval;
        emit uploadIntervalChanged(m_uploadInterval);
    }

    void setReuploadInterval(qlonglong reuploadInterval)
    {
        if (m_reuploadInterval == reuploadInterval)
            return;

        m_reuploadInterval = reuploadInterval;
        emit reuploadIntervalChanged(m_reuploadInterval);
    }

    void setUploadState(UploadState uploadState)
    {
        if (m_uploadState == uploadState)
            return;

        m_uploadState = uploadState;
        emit uploadStateChanged(m_uploadState);
    }

    void setUploadRealm(QString uploadRealm)
    {
        if (m_uploadRealm == uploadRealm)
            return;

        m_uploadRealm = uploadRealm;
        emit uploadRealmChanged(m_uploadRealm);
    }

signals:
    //	property signals
    void numOfUploadedLinesChanged(qlonglong numOfUploadedLines);
    void numOfReuploadedLinesChanged(qlonglong numOfReuploadedLines);
    void uploadIntervalChanged(qlonglong uploadInterval);
    void reuploadIntervalChanged(qlonglong reuploadInterval);
    void uploadStateChanged(UploadState uploadState);
    void uploadRealmChanged(QString uploadRealm);
};

#endif
